using System;
using UnityEngine;
using System.Collections.Generic;

public class KICOITController : PartModule {
	protected Rect windowPos;
	public ShipData ship = new ShipData ();
	private PartModule.StartState state;
	private ConsultantManager manager = new ConsultantManager ();
	public static Engineer activeEngineer;
	//private bool debug = false;
	private Vector2 scroll = new Vector2 ();
	private string consultant = "KICOIT Basic Stats";
		
	private void computeShip () {
		Debug.Log ("clear consultants");
		manager.ClearConsultants ();
		Debug.Log ("get consultants");
		getConsultants ();
		Debug.Log ("calculate ship");
		calculateShipInfo ();
		Debug.Log ("analize ship");
		manager.AnalizeShip (ship);
	}

	private void calculateShipInfo () {
		Debug.Log ("clear ship data");
		ship.ClearData ();
		Debug.Log ("walkparts");
		Part p = this.part;
		while (p.parent)
			p = p.parent;
		walkParts (p);
		Debug.Log ("calculate totals by stage");
		ship.calculateTotals ();
			
	}

	private void getConsultants () {
		BaseEventData d = new BaseEventData (BaseEventData.Sender.AUTO);
		d.Set<ConsultantManager> ("Manager", manager);
		part.SendEvent ("RegisterConsultant", d);
	}
		
	public override void OnStart (StartState state) {
		Debug.Log ("controller onstart state is: " + state);
		this.state = state;
		base.OnStart (state);
		if (windowPos.x == 0 && windowPos.y == 0) {
			windowPos = new Rect (Screen.width / 4, Screen.height / 8, 400, 400);
		}
		if (this.part.parent) {
			//probably loaded instead of being a new part
			this.OnBackup ();
		}
	}

	private void walkParts (Part p) {
		StageData stage = ship.getStage (p.inverseStage);
			
		if (!(p is Engineer)) {
			stage.parts += 1;
			stage.mass += p.mass;
			stage.cost += p.partInfo.cost;
		}
		if (p is FuelTank) {
			stage.parts += 1;
			stage.fuel += (p as FuelTank).fuel;
			stage.tankweight += p.mass;
			stage.fuelMass += p.mass - (p as FuelTank).dryMass;
			//TODO find lost weight
			//calculate fuel mass (m_tf - m_te) /fuel
			
		} else if (p is LiquidEngine) {
			stage.thrust += (p as LiquidEngine).maxThrust;	
		} else if (p is SolidRocket) {
			stage.thrust += (p as SolidRocket).thrust;
		} else if (p is RCSFuelTank) {
			stage.rcs += (p as RCSFuelTank).fuel;
		} else if (p is AtmosphericEngine) {
			stage.airthrust += (p as AtmosphericEngine).maximumEnginePower;
		}
			
		manager.AnalizePart (p, ship);
		
		if (!stage.partlist.ContainsKey(p.ClassName)) stage.partlist.Add(p.ClassName, new List<Part>());
		stage.partlist[p.ClassName].Add(p);
		Debug.Log(p.ClassName);
		foreach (Part c in p.children) {
			walkParts (c);
		}
			
	}

	private void debugPartOutput (Part p) {// TODO need to recheck
		print ("");
		print (p.name);
		print ("original stage: " + p.originalStage);
		print ("default inverseStage: " + p.defaultInverseStage);
		print ("inverse stage: " + p.inverseStage);//this guy is our guy
		print ("in stage index: " + p.inStageIndex);
		print ("child stage offset: " + p.childStageOffset);
		print ("manual stage offset: " + p.manualStageOffset);
		print ("stage offset: " + p.stageOffset);
		print ("stage after: " + p.stageAfter);
		print ("stage before: " + p.stageBefore);
	}
		
	private void drawGUI () {
		GUI.skin = HighLogic.Skin;
		windowPos = GUILayout.Window (
				4,
				windowPos,
				WindowGUI,
				"Engineer",
				GUILayout.MinWidth (400)
		);
	}

	public void OnBackup () {
		Debug.Log ("controller on backup");
		if (this.part == activeEngineer && this.state == PartModule.StartState.Editor) {
			Debug.Log ("just compute");
			computeShip ();
		} else if (!isRendering () && !this.part.isClone && this.state == PartModule.StartState.Editor) {
			Debug.Log ("set self as active and compute");
			activeEngineer = this.part as Engineer;
			computeShip ();
			RenderingManager.AddToPostDrawQueue (4, new Callback (drawGUI));
			
		} else {
			Debug.Log ("not active engineer");
			//Debug.Log("active engineer is: " + activeEngineer.name);
		}
	}

	private void WindowGUI (int windowID) {
		//Debug.Log("controller windowGUI");
		if (isRendering () && this.state == PartModule.StartState.Editor) {
			GUIStyle sty = new GUIStyle (GUI.skin.textArea);//gives the look of a textArea with the feel of a label
			sty.alignment = TextAnchor.MiddleCenter;
			sty.fontStyle = FontStyle.Bold;
			
			//back button and current name
			GUILayout.BeginHorizontal (GUILayout.MaxHeight (25));
			if (consultant == "")
				GUI.enabled = false;
			if (GUILayout.Button ("List", GUILayout.MaxWidth (100)))
				consultant = "";
			GUI.enabled = true;
			
			if (consultant == "")
				GUILayout.Label ("Consultants", sty);//TODO decide what the list should say
			else
				GUILayout.Label (consultant, sty);
			
			GUILayout.EndHorizontal ();
			//scrollable area
			scroll = GUILayout.BeginScrollView (scroll);
			if (consultant == "") {
				foreach (string c in manager.GetConsultantList()) {
					if (GUILayout.Button (c)) {
						//save string to use
						consultant = c;
					}
				}
			} else
				manager.drawConsultant (consultant, ship);
			
			GUILayout.EndScrollView ();
				
			GUI.DragWindow ();
		} else {
			Debug.Log ("controller remove window");
			RenderingManager.RemoveFromPostDrawQueue (4, new Callback (drawGUI));
			activeEngineer = null;
		}
	}

	private bool isRendering () {
		if (!activeEngineer || activeEngineer == null) {
			return false;
		} else if (!activeEngineer.parent) {
			return false;
		} else if (activeEngineer == this.part) {
			return true;
		}
		return false;
		
	}
}


